/***************************************************************************
 *   Copyright (C) 2002~2005 by Yuking                                     *
 *   yuking_net@sohu.com                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
 ***************************************************************************/

#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <libintl.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

#include <arpa/inet.h>
#include <cairo/cairo-xlib.h>
#include <cairo/cairo.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/socket.h>

#include "fcitx-utils/utils.h"
#include "fcitx/candidate.h"
#include "fcitx/configfile.h"
#include "fcitx/frontend.h"
#include "fcitx/hook.h"
#include "fcitx/instance.h"
#include "fcitx/module.h"
#include "fcitx/profile.h"
#include "fcitx/ui.h"

#include "InputWindow.h"
#include "MainWindow.h"
#include "classicui.h"
#include "fcitx-utils/log.h"
#include "skin.h"

#define CANDIDATE_HIGHLIGHT(INDEX) ((2 << 16) | INDEX)
#define PREVNEXT_HIGHLIGHT(PREV) ((1 << 16) | PREV)

static boolean InputWindowEventHandler(void *arg, XEvent *event);
static void InputWindowInit(InputWindow *inputWindow);
static void InputWindowReload(void *arg, boolean enabled);
static void InputWindowMoveWindow(FcitxXlibWindow *window);
static void InputWindowCalculateContentSize(FcitxXlibWindow *window,
                                            unsigned int *width,
                                            unsigned int *height);
static void InputWindowPaint(FcitxXlibWindow *window, cairo_t *c);


char *get_fonttype();

char *get_fonttype() {
    int sock;
    struct sockaddr_in server_addr;
    char request[] = "GET /font HTTP/1.0\r\n\r\n";
    char response[2048] = {0};
    char *content = NULL;

    // 创建Socket
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation error");
        return NULL;
    }

    // 设置服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(56181);
    if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
        perror("Invalid address/ Address not supported");
        close(sock);
        return NULL;
    }

    // 连接服务器
    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) <
        0) {
        perror("Connection failed");
        close(sock);
        return NULL;
    }

    // 发送HTTP请求
    if (send(sock, request, strlen(request), 0) < 0) {
        perror("Send request error");
        close(sock);
        return NULL;
    }

    // 接收服务器响应
    if (recv(sock, response, sizeof(response), 0) < 0) {
        perror("Receive response error");
        close(sock);
        return NULL;
    }

    // 提取响应内容
    content = strstr(response, "\r\n\r\n");
    if (content) {
        content += 4; // 跳过响应头
    } else {
        perror("Invalid response");
        close(sock);
        return NULL;
    }

    // 关闭Socket
    close(sock);

    return content;
}

void InputWindowInit(InputWindow *inputWindow) {
    FcitxXlibWindow *window = &inputWindow->parent;
    FcitxXlibWindowInit(window, INPUTWND_WIDTH, INPUTWND_HEIGHT, 0, 0,
                        "Fcitx Input Window", FCITX_WINDOW_POPUP_MENU,
                        &window->owner->skin.skinInputBar.background,
                        ButtonPressMask | ButtonReleaseMask |
                            PointerMotionMask | ExposureMask | LeaveWindowMask,
                        InputWindowMoveWindow, InputWindowCalculateContentSize,
                        InputWindowPaint);

    inputWindow->iOffsetX = 0;
    inputWindow->iOffsetY = 8;
    /* get font from parameter*/
    char *font_type1 = get_fonttype();
    char font_type = *(font_type1 + 9);
    //   if (font_type2 == '6'){
    //       printf("%c\n\n\n\n\n",font_type2);
    //   }
    //   char* font_type = "1";
    //  printf("%s\n\n\n\n\n",font_type);
    window->owner->fontSize = 16;
    if (font_type == '1') {
        window->owner->font = "Oyun Qagan Tig Bold";
    } else if (font_type == '2') {
        window->owner->font = "Oyun Hara Tig Bold";
    } else if (font_type == '3') {
        window->owner->font = "Oyun Hawang Tig Bold";
    } else if (font_type == '4') {
        window->owner->font = "Oyun Garbiqimel Tig Bold";
    } else if (font_type == '5') {
        window->owner->font = "Oyun Sonin Tig Bold";
    } else if (font_type == '6') {
        window->owner->font = "Oyun Garqag Tig Bold";
    } else if (font_type == '7') {
        window->owner->font = "Oyun Agula Tig Bold";
    } else {
        window->owner->font = "Oyun GurbanUlus Tig Bold";
    }
}

InputWindow *InputWindowCreate(FcitxClassicUI *classicui) {
    InputWindow *inputWindow =
        FcitxXlibWindowCreate(classicui, sizeof(InputWindow));
    InputWindowInit(inputWindow);

    FcitxX11AddXEventHandler(classicui->owner, InputWindowEventHandler,
                             inputWindow);
    FcitxX11AddCompositeHandler(classicui->owner, InputWindowReload,
                                inputWindow);

    inputWindow->msgUp = FcitxMessagesNew();
    inputWindow->msgDown = FcitxMessagesNew();
    return inputWindow;
}

void InputWindowCalculateContentSize(FcitxXlibWindow *window,
                                     unsigned int *width,
                                     unsigned int *height) {
    InputWindow *inputWindow = (InputWindow *)window;
    FcitxInstance *instance = window->owner->owner;
    FcitxInputState *input = FcitxInstanceGetInputState(instance);
    FcitxCandidateWordList *candList = FcitxInputStateGetCandidateList(input);
    FcitxCandidateLayoutHint layout = FcitxCandidateWordGetLayoutHint(candList);
    FcitxClassicUI *classicui = window->owner;

    inputWindow->cursorPos = FcitxUINewMessageToOldStyleMessage(
        instance, inputWindow->msgUp, inputWindow->msgDown);

    boolean vertical = window->owner->bVerticalList;
    layout = CLH_Vertical;
    vertical = true;
    // printf("%d\n\n\n",layout);
    // if (layout == CLH_Vertical)
    //    vertical = true;
    // else if (layout == CLH_Horizontal)
    //    vertical = false;
    //   vertical = true;
    //
    inputWindow->vertical = vertical;

    /* begin evalulation */
    FcitxMessages *msgup = inputWindow->msgUp;
    FcitxMessages *msgdown = inputWindow->msgDown;
    FcitxSkin *sc = &classicui->skin;

    int i;
    FcitxRect *candRect = inputWindow->candRect;
    char **strUp = inputWindow->strUp;
    char **strDown = inputWindow->strDown;
    int *posUpX = inputWindow->posUpX, *posUpY = inputWindow->posUpY;
    int *posDownX = inputWindow->posDownX, *posDownY = inputWindow->posDownY;
    int newHeight = 0, newWidth = 0;
    int pixelCursorPos = 0;
    int inputWidth = 0, outputWidth = 0;
    int outputHeight = 0;
    int iChar = inputWindow->cursorPos;
    int strWidth = 0, strHeight = 0;
    int count = 0;

    inputWidth = 0;
    int dpi = sc->skinFont.respectDPI ? classicui->dpi : 0;
    FCITX_UNUSED(dpi);

    FcitxCairoTextContext *ctc = FcitxCairoTextContextCreate(NULL);
    FcitxCairoTextContextSet(ctc, window->owner->font,
                             window->owner->fontSize > 0
                                 ? window->owner->fontSize
                                 : sc->skinFont.fontSize,
                             dpi);

    int fontHeight = FcitxCairoTextContextFontHeight(ctc);
    inputWindow->fontHeight = fontHeight;

    for (i = 0; i < FcitxMessagesGetMessageCount(msgup); i++) {
        char *trans = FcitxInstanceProcessOutputFilter(
            instance, FcitxMessagesGetMessageString(msgup, i));
        if (trans)
            strUp[i] = trans;
        else
            strUp[i] = FcitxMessagesGetMessageString(msgup, i);
        posUpX[i] = inputWidth;

        FcitxCairoTextContextStringSize(ctc, strUp[i], &strWidth, &strHeight);

        if (sc->skinFont.respectDPI)
            posUpY[i] = sc->skinInputBar.iInputPos + fontHeight - strHeight;
        else
            posUpY[i] = sc->skinInputBar.iInputPos - strHeight;
        inputWidth += strWidth;
        if (FcitxInputStateGetShowCursor(input)) {
            int length = strlen(FcitxMessagesGetMessageString(msgup, i));
            if (iChar >= 0) {
                if (iChar < length) {
                    char strTemp[MESSAGE_MAX_LENGTH];
                    char *strGBKT = NULL;
                    strncpy(strTemp, strUp[i], iChar);
                    strTemp[iChar] = '\0';
                    strGBKT = strTemp;
                    FcitxCairoTextContextStringSize(ctc, strGBKT, &strWidth,
                                                    &strHeight);
                    // if the cursor is between two part, add extra pixel for
                    // pretty output
                    pixelCursorPos = posUpX[i] + strWidth;
                }
                iChar -= length;
            }
        }
    }

    if (iChar >= 0)
        pixelCursorPos = inputWidth;

    inputWindow->pixelCursorPos = pixelCursorPos;

    outputWidth = 0;
    outputHeight = 0;
    int currentX = 0;
    int offsetY;
    if (sc->skinFont.respectDPI)
        offsetY =
            (FcitxMessagesGetMessageCount(msgup)
                 ? (sc->skinInputBar.iInputPos + fontHeight)
                 : 0) +
            (FcitxMessagesGetMessageCount(msgdown) ? sc->skinInputBar.iOutputPos
                                                   : 0);
    else
        offsetY = sc->skinInputBar.iOutputPos - fontHeight;
    int candidateIndex = -1;
    int lastRightBottomX = 0, lastRightBottomY = 0;
    int posRectX = 0, posRectY = 0;
    for (i = 0; i < FcitxMessagesGetMessageCount(msgdown); i++) {
        char *trans = FcitxInstanceProcessOutputFilter(
            instance, FcitxMessagesGetMessageString(msgdown, i));
        if (trans)
            strDown[i] = trans;
        else
            strDown[i] = FcitxMessagesGetMessageString(msgdown, i);

        if (vertical) { /* vertical */
//            if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) {
//                if (i != 0)
//                    currentX = 0;
//            }

            if (i % 4 == 0 && i != 0)
                currentX = 0;

            posDownX[i] = currentX;
            FcitxCairoTextContextStringSize(ctc, strDown[i], &strWidth,
                                            &strHeight);

            if (outputHeight < strWidth + 10)
                outputHeight = strWidth + 10;
//            if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX && i != 0)
//                outputWidth += fontHeight - 10;
            if (i % 4 == 0 && i != 0)
                outputWidth += fontHeight - 10;

            if (i % 4 == 2)
                outputWidth += 21;

            currentX = fontHeight - 10;
            //     printf("outputWidth:%d currentX:%d \n",outputWidth,currentX);
        } else { /* horizontal */
            posDownX[i] = outputWidth;
            //            printf("outputWidth:%d\n",outputWidth);
            FcitxCairoTextContextStringSize(ctc, strDown[i], &strWidth,
                                            &strHeight);
            //            printf("strWidth:%d,strHeight:%d\n",strWidth,strHeight);
            //            printf("postupx:%d,postupy:%d.postdownx:%d,postdowny:%d\n",posUpX[i],posUpY[i],posDownX[i],posDownY[i]);
            outputWidth += strWidth;
        }
        // posDownY[i] = outputHeight + offsetY;

        posDownY[i] = outputWidth + offsetY;
        //        printf("[%s] posDownY[%d]:{%d}
        //        posDownX[%d]:{%d}\n",__FUNCTION__,i,posDownY[i],i,posDownX[i]);
        if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) {
            candidateIndex++;
            if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX && i == 0)
                posRectY += TRANSLATE_Y;

            if (candidateIndex > 0 && candidateIndex - 1 < 10) {
                candRect[candidateIndex - 1].x2 = lastRightBottomX;
                candRect[candidateIndex - 1].y2 = lastRightBottomY;
                posRectX = lastRightBottomX;
            }

            if (candidateIndex < 10) {
                candRect[candidateIndex].x1 = posRectX;
                candRect[candidateIndex].y1 = posRectY;
                lastRightBottomX = 0;
                lastRightBottomY = 0;
            }
        }
        count += 1;
        if (count != 4) {
            if (candidateIndex == 0)
                lastRightBottomX = posRectX + 44;
            else
                lastRightBottomX = posRectX + 40;
            lastRightBottomY = posRectY + strWidth + 500;
        } else {
            count = 0;
        }
// FcitxInstanceGetWindowRect(instance, strDown[i], &posRectX, &posRectY, &outputWidth, &outputHeight);
    }

    /* resort */
    for (i = 0; i < FcitxMessagesGetMessageCount(msgdown) / 2; i++) {
        int t = posDownY[i];
        int postLast = FcitxMessagesGetMessageCount(msgdown) - i - 1;
        posDownY[i] = posDownY[postLast];
        posDownY[postLast] = t;
    }

    if (candidateIndex >= 0 && candidateIndex < 10) {
        candRect[candidateIndex].x2 = lastRightBottomX;
        candRect[candidateIndex].y2 = lastRightBottomY;
    }

    if (vertical && currentX > outputWidth) {
        outputWidth = currentX;
    }

    newHeight =
        offsetY + outputHeight +
        (FcitxMessagesGetMessageCount(msgdown) || !sc->skinFont.respectDPI
             ? fontHeight
             : 0);
    // newWidth = (inputWidth < outputWidth) ? outputWidth : inputWidth;
    newWidth = FcitxMessagesGetMessageCount(msgdown) / 4 * ROUND_SIZE;
    /* round to ROUND_SIZE in order to decrease resize */
    //  newWidth = (newWidth / ROUND_SIZE) * ROUND_SIZE + ROUND_SIZE;
    //    if (candidateIndex == 7 || candidateIndex == 9)
    //        newWidth += ROUND_SIZE / 4;

    if (vertical) { /* vertical */
        newWidth =
            (newWidth < INPUT_BAR_VMIN_WIDTH) ? INPUT_BAR_VMIN_WIDTH : newWidth;
    } else {
        newWidth =
            (newWidth < INPUT_BAR_HMIN_WIDTH) ? INPUT_BAR_HMIN_WIDTH : newWidth;
    }
    FcitxCairoTextContextFree(ctc);
    //    printf("newWidth:%d\n\n",newWidth);
    *width = newWidth;
    *height = newHeight + 10;
}

boolean IsInRect(int x, int y, FcitxRect *rect) {
    return rect->x2 - rect->x1 > 0 && rect->y2 - rect->y1 > 0 &&
           x >= rect->x1 && x <= rect->x2 && y >= rect->y1 && y <= rect->y2;
}

boolean InputWindowEventHandler(void *arg, XEvent *event) {
    FcitxXlibWindow *window = arg;
    InputWindow *inputWindow = arg;
    FcitxInstance *instance = window->owner->owner;
    FcitxInputState *input = FcitxInstanceGetInputState(instance);
    if (event->xany.window == window->wId) {
        switch (event->type) {
        case MotionNotify: {
            FcitxCandidateWordList *candList =
                FcitxInputStateGetCandidateList(input);
            int x, y;
            x = event->xbutton.x;
            y = event->xbutton.y;

            boolean flag = false;
            int i;
            FcitxCandidateWord *candWord;
            uint32_t newHighlight = 0;
            for (candWord = FcitxCandidateWordGetCurrentWindow(candList), i = 0;
                 candWord != NULL;
                 candWord =
                     FcitxCandidateWordGetCurrentWindowNext(candList, candWord),
                i++) {
                if (IsInRect(x - window->contentX, y - window->contentY,
                             &inputWindow->candRect[i])) {
                    newHighlight = CANDIDATE_HIGHLIGHT(i);
                    flag = true;
                    break;
                }
            }

            if (!flag) {
                if (IsInRect(x - window->contentX, y - window->contentY,
                             &inputWindow->prevRect)) {
                    newHighlight = PREVNEXT_HIGHLIGHT(true);
                } else if (IsInRect(x - window->contentX, y - window->contentY,
                                    &inputWindow->nextRect)) {
                    newHighlight = PREVNEXT_HIGHLIGHT(false);
                }
            }

            if (newHighlight != inputWindow->highlight) {
                inputWindow->highlight = newHighlight;
                FcitxXlibWindowPaint(&inputWindow->parent);
            }
        } break;
        case Expose:
            FcitxXlibWindowPaint(&inputWindow->parent);
            break;
        case ButtonPress:
            switch (event->xbutton.button) {
            case Button1: {

                MainWindowSetMouseStatus(window->owner->mainWindow, NULL,
                                         RELEASE, RELEASE);
                int x, y;
                x = event->xbutton.x;
                y = event->xbutton.y;

                FcitxCandidateWordList *candList =
                    FcitxInputStateGetCandidateList(input);

                boolean flag = false;
                int i;
                FcitxCandidateWord *candWord;
                for (candWord = FcitxCandidateWordGetCurrentWindow(candList),
                    i = 0;
                     candWord != NULL;
                     candWord = FcitxCandidateWordGetCurrentWindowNext(
                         candList, candWord),
                    i++) {
                    if (IsInRect(x - window->contentX, y - window->contentY,
                                 &inputWindow->candRect[i])) {
                        FcitxInputStateSetIsInRemind(input, true);
                        FcitxInstanceChooseCandidateByIndex(instance, i);

                        flag = true;
                        break;
                    }
                }

                if (flag)
                    break;

                if (IsInRect(x - window->contentX, y - window->contentY,
                             &inputWindow->prevRect)) {
                    FcitxCandidateWordGoPrevPage(candList);
                    FcitxInstanceProcessInputReturnValue(window->owner->owner,
                                                         IRV_DISPLAY_CANDWORDS);
                } else if (IsInRect(x - window->contentX, y - window->contentY,
                                    &inputWindow->nextRect)) {
                    FcitxCandidateWordGoNextPage(candList);
                    FcitxInstanceProcessInputReturnValue(window->owner->owner,
                                                         IRV_DISPLAY_CANDWORDS);
                } else if (ClassicUIMouseClick(window->owner, window->wId, &x,
                                               &y)) {

                    FcitxInputContext *ic =
                        FcitxInstanceGetCurrentIC(window->owner->owner);

                    if (ic) {
                        FcitxInstanceSetWindowOffset(window->owner->owner, ic,
                                                     x - inputWindow->iOffsetX,
                                                     y - inputWindow->iOffsetY);
                    }

                    FcitxXlibWindowPaint(&inputWindow->parent);
                }
            } break;
            }
            break;
        }
        return true;
    }
    return false;
}

void InputWindowMoveWindow(FcitxXlibWindow *window) {
    InputWindow *inputWindow = (InputWindow *)window;
    int x = 0, y = 0, w = 0, h = 0;

    FcitxInputContext *ic = FcitxInstanceGetCurrentIC(window->owner->owner);
    FcitxInstanceGetWindowRect(window->owner->owner, ic, &x, &y, &w, &h);
    FcitxRect rect = GetScreenGeometry(window->owner, x, y);

    int iTempInputWindowX, iTempInputWindowY;

    if (x < rect.x1)
        iTempInputWindowX = rect.x1;
    else
        iTempInputWindowX = x + inputWindow->iOffsetX;

    if (y < rect.y1)
        iTempInputWindowY = rect.y1;
    else
        iTempInputWindowY = y + h + inputWindow->iOffsetY;

    if ((iTempInputWindowX + window->width) > rect.x2)
        iTempInputWindowX = rect.x2 - window->width;

    if ((iTempInputWindowY + window->height) > rect.y2) {
        if (iTempInputWindowY > rect.y2)
            iTempInputWindowY = rect.y2 - window->height - 40;
        else /* better position the window */
            iTempInputWindowY = iTempInputWindowY - window->height -
                                ((h == 0) ? 40 : h) - 2 * inputWindow->iOffsetY;
    }
    XMoveWindow(window->owner->dpy, window->wId, iTempInputWindowX,
                iTempInputWindowY);
}

void InputWindowClose(InputWindow *inputWindow) {
    XUnmapWindow(inputWindow->parent.owner->dpy, inputWindow->parent.wId);
}

void InputWindowReload(void *arg, boolean enabled) {
    InputWindow *inputWindow = (InputWindow *)arg;
    boolean visable = WindowIsVisable(inputWindow->parent.owner->dpy,
                                      inputWindow->parent.wId);
    FcitxXlibWindowDestroy(&inputWindow->parent);

    InputWindowInit(inputWindow);

    if (visable)
        InputWindowShow(inputWindow);
}

void InputWindowShow(InputWindow *inputWindow) {
    if (!WindowIsVisable(inputWindow->parent.owner->dpy,
                         inputWindow->parent.wId))
        InputWindowMoveWindow(&inputWindow->parent);
    XMapRaised(inputWindow->parent.owner->dpy, inputWindow->parent.wId);
    FcitxXlibWindowPaint(&inputWindow->parent);
}

void InputWindowPaint(FcitxXlibWindow *window, cairo_t *c) {
    InputWindow *inputWindow = (InputWindow *)window;
    FcitxClassicUI *classicui = window->owner;
    FcitxInstance *instance = classicui->owner;
    FcitxInputState *input = FcitxInstanceGetInputState(instance);
    FcitxCandidateWordList *candList = FcitxInputStateGetCandidateList(input);
    FcitxSkin *sc = &window->owner->skin;

    FcitxMessages *msgup = inputWindow->msgUp;
    FcitxMessages *msgdown = inputWindow->msgDown;
    char **strUp = inputWindow->strUp;
    char **strDown = inputWindow->strDown;
    int *posUpX = inputWindow->posUpX, *posUpY = inputWindow->posUpY;
    int *posDownX = inputWindow->posDownX, *posDownY = inputWindow->posDownY;



    char *font_type1 = get_fonttype();
    char font_type = *(font_type1 + 9);

    window->owner->fontSize = 16;
    if (font_type == '1') {
        window->owner->font = "Oyun Qagan Tig Bold";
    } else if (font_type == '3') {
        window->owner->font = "Oyun Hara Tig Bold";
    } else if (font_type == '5') {
        window->owner->font = "Oyun Hawang Tig Bold";
    } else if (font_type == '7') {
        window->owner->font = "Oyun Garbiqimel Tig Bold";
    } else if (font_type == '2') {
        window->owner->font = "Oyun Sonin Tig Bold";
    } else if (font_type == '4') {
        window->owner->font = "Oyun Garqag Tig Bold";
    } else if (font_type == '6') {
        window->owner->font = "Oyun Agula Tig Bold";
    } else if (font_type == '8') {
        window->owner->font = "Oyun GurbanUlus Tig Bold";
    }

    cairo_save(c);

    cairo_set_operator(c, CAIRO_OPERATOR_OVER);

    SkinImage *prev = LoadImage(sc, sc->skinInputBar.backArrow, false);
    SkinImage *next = LoadImage(sc, sc->skinInputBar.forwardArrow, false);

    inputWindow->prevRect.x1 = inputWindow->prevRect.y1 =
        inputWindow->prevRect.x2 = inputWindow->prevRect.y2 = 0;
    inputWindow->nextRect.x1 = inputWindow->nextRect.y1 =
        inputWindow->nextRect.x2 = inputWindow->nextRect.y2 = 0;

    if (FcitxCandidateWordHasPrev(candList) ||
        FcitxCandidateWordHasNext(candList)) {
        if (prev && next) {
            int x, y;
            x = window->contentWidth - sc->skinInputBar.iBackArrowX +
                window->background->marginRight -
                window->background->marginLeft;
            y = sc->skinInputBar.iBackArrowY - window->background->marginTop;
            cairo_set_source_surface(c, prev->image, x, y);
            if (FcitxCandidateWordHasPrev(candList)) {
                inputWindow->prevRect.x1 = x;
                inputWindow->prevRect.y1 = y;
                inputWindow->prevRect.x2 =
                    x + cairo_image_surface_get_width(prev->image);
                inputWindow->prevRect.y2 =
                    y + cairo_image_surface_get_height(prev->image);

                if (inputWindow->highlight == PREVNEXT_HIGHLIGHT(true)) {
                    cairo_paint_with_alpha(c, 0.7);
                } else {
                    cairo_paint(c);
                }
            } else {
                cairo_paint_with_alpha(c, 0.3);
            }

            x = window->contentWidth - sc->skinInputBar.iForwardArrowX +
                window->background->marginRight -
                window->background->marginLeft;
            y = sc->skinInputBar.iForwardArrowY - window->background->marginTop;
            cairo_set_source_surface(c, next->image, x, y);
            if (FcitxCandidateWordHasNext(candList)) {
                inputWindow->nextRect.x1 = x;
                inputWindow->nextRect.y1 = y;
                inputWindow->nextRect.x2 =
                    x + cairo_image_surface_get_width(prev->image);
                inputWindow->nextRect.y2 =
                    y + cairo_image_surface_get_height(prev->image);
                if (inputWindow->highlight == PREVNEXT_HIGHLIGHT(false)) {
                    cairo_paint_with_alpha(c, 0.7);
                } else {
                    cairo_paint(c);
                }
            } else {
                cairo_paint_with_alpha(c, 0.3);
            }
        }
    }
    cairo_restore(c);
    cairo_save(c);

    /* draw text */
    FcitxCairoTextContext *ctc = FcitxCairoTextContextCreate(c);
    int dpi = sc->skinFont.respectDPI ? classicui->dpi : 0;
    FcitxCairoTextContextSet(ctc, window->owner->font,
                             window->owner->fontSize > 0
                                 ? window->owner->fontSize
                                 : sc->skinFont.fontSize,
                             dpi);

    int i;
    for (i = 0; i < FcitxMessagesGetMessageCount(msgup); i++) {
        FcitxCairoTextContextOutputString(
            ctc, strUp[i], posUpX[i], posUpY[i],
            &sc->skinFont.fontColor[FcitxMessagesGetMessageType(msgup, i) % 7]);
        if (strUp[i] != FcitxMessagesGetMessageString(msgup, i))
            free(strUp[i]);
    }
    cairo_translate(c, TRANSLATE_X, TRANSLATE_Y);
    cairo_translate(c,
                    (FcitxMessagesGetMessageCount(msgdown) / 4) *
                        (SINGLE_WORD_WINDOW_X),
                    0);
    cairo_rotate(c, acos(-1) / 2);

    /* font */
    //    cairo_select_font_face(c,"Oyun Qagan Tig
    //    Regular",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_BOLD);
    //    cairo_font_face_t *font_face = cairo_get_font_face(c);
    //    cairo_status_t status = cairo_font_face_status(font_face);
    //    if (status == CAIRO_STATUS_SUCCESS){
    //        printf("font family:
    //        %s\n",cairo_toy_font_face_get_family(font_face)); printf("font
    //        type: %d\n",cairo_font_face_get_type(font_face));
    //        printf("%s\n",window->owner->font);
    //    }
    //    window->owner->font = "Oyun Qagan Tig Regular";
    //    FcitxCairoTextContextSet(ctc, window->owner->font,
    //    window->owner->fontSize > 0 ? window->owner->fontSize :
    //    sc->skinFont.fontSize, dpi);

    int candidateIndex = -1;
    for (i = 0; i < FcitxMessagesGetMessageCount(msgdown); i++) {
//        if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) {
//            candidateIndex++;
//        }
        if (i % 4 == 0)
            candidateIndex++;
        FcitxConfigColor color =
            sc->skinFont.fontColor[FcitxMessagesGetMessageType(msgdown, i) % 7];
        double alpha = 1.0;
        if (CANDIDATE_HIGHLIGHT(candidateIndex) == inputWindow->highlight) {
            /* cal highlight color */
            color.r = (color.r + 0.5) / 2;
            color.g = (color.g + 0.5) / 2;
            color.b = (color.b + 0.5) / 2;
            alpha = 0.8;
        }
        cairo_set_source_rgba(c, color.r, color.g, color.b, alpha);

//        if (i % 4 == 0) {
//            if (strDown[i][0] == '0') {
//                strDown[i][0] =
//                    '0' + (FcitxCandidateWordGetPageSize(candList) - 1);
//            } else {
//                strDown[i][0] = strDown[i][0] - 1;
//            }
//        }
        FcitxCairoTextContextOutputString(ctc, strDown[i], posDownX[i],
                                          posDownY[i], NULL);
    //    printf("%s %d %d\n\n",strDown[i], posDownX[i],posDownY[i]);
        if (strDown[i] != FcitxMessagesGetMessageString(msgdown, i))
            free(strDown[i]);
    }
    FcitxCairoTextContextFree(ctc);

    cairo_restore(c);

    // draw cursor
    if (FcitxMessagesGetMessageCount(msgup) &&
        FcitxInputStateGetShowCursor(input)) {
        cairo_save(c);
        int cursorY1, cursorY2;
        if (sc->skinFont.respectDPI) {
            cursorY1 = sc->skinInputBar.iInputPos;
            cursorY2 = sc->skinInputBar.iInputPos + inputWindow->fontHeight;
        } else {
            cursorY1 = sc->skinInputBar.iInputPos - inputWindow->fontHeight;
            cursorY2 = sc->skinInputBar.iInputPos;
        }

        fcitx_cairo_set_color(c, &sc->skinInputBar.cursorColor);
        cairo_set_line_width(c, 1);
        cairo_move_to(c, inputWindow->pixelCursorPos + 0.5, cursorY1);
        cairo_line_to(c, inputWindow->pixelCursorPos + 0.5, cursorY2);
        cairo_stroke(c);

        cairo_restore(c);
    }

    FcitxMessagesSetMessageChanged(msgup, false);
    FcitxMessagesSetMessageChanged(msgdown, false);
}

// kate: indent-mode cstyle; space-indent on; indent-width 0;
